﻿using Audio.Diagnostics;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Windows.Storage;

namespace Audio
{
    public class AudioSaver
    {
        public bool IsEnabled { get; set; } = false;
        private readonly SemaphoreSlim outputFileSemaphore = new SemaphoreSlim(1, 1);
        private Stream outputFileStream;

        private StorageFolder storageFolder = null;
        private string file = "";

        public async Task CreateAsync(StorageFolder folder, string filename)
        {
            if (!IsEnabled) return;

            await outputFileSemaphore.WaitAsync();

            storageFolder = folder;
            file = filename;
            try
            {
                Debug.WriteLine($"AudioSaver, CreateAsync, {filename}");
                if (this.outputFileStream == null)
                {
                    this.outputFileStream = await folder.OpenStreamForWriteAsync(filename, CreationCollisionOption.ReplaceExisting).ConfigureAwait(false);
                    this.outputFileStream.Write(new byte[44], 0, 44);

                    Debug.WriteLine($"{filename} is created!");
                }
            }
            catch(Exception ex)
            {
                Debug.WriteLine($"AudioSaver Create failed. ex: Message:{ex.Message}, stacktrace:{ex.StackTrace}");
            }
            finally
            {
                outputFileSemaphore.Release();
            }
        }
        public async Task Push(byte[]data, int len)
        {
            if (!IsEnabled) return;
            await outputFileSemaphore.WaitAsync();
            try
            {
                this.outputFileStream?.Write(data, 0, len);
            }
            finally
            {
                outputFileSemaphore.Release();
            }
        }

        public async Task Save()
        {
            if (!IsEnabled) return;

            Debug.WriteLine($"AudioSaver, Save, {file}");

            await this.outputFileSemaphore.WaitAsync();
            
            try
            {
                if (this.outputFileStream != null)
                {
                    Wave.WriteHeader(outputFileStream, false, 1, 16, 16000, (int)outputFileStream.Length);
                    this.outputFileStream.Flush();
                    this.outputFileStream.Close();
                    this.outputFileStream.Dispose();
                    this.outputFileStream = null;

                    Debug.WriteLine($"Save cognitive audio.");
                }
            }
            catch(Exception ex)
            {
                Debug.WriteLine($"AudioSaver Save failed. ex: Message:{ex.Message}, stacktrace:{ex.StackTrace}");
            }
            finally
            {
                this.outputFileSemaphore.Release();
            }
        }

        public async Task RenameAsync(string newName)
        {
            try
            {
                if (string.IsNullOrEmpty(file)) return;
                var storageFile = await storageFolder?.GetFileAsync(file);
                await storageFile?.RenameAsync(newName);
                Debug.WriteLine($"Change file from {storageFile?.Name} to {newName} successfully.");
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"Change filename to {newName} failed. ex: Message:{ex.Message}, stacktrace:{ex.StackTrace}");
            }
        }
    }
}
